import G6 from '@antv/g6'
import insertCss from 'insert-css'
import getThemeColor from '@/utils/themesColor'
import store from '@/store'
import { deepClone } from '@/utils/common'

insertCss(`
  .g6-minimap-viewport {
    border: 1px solid rgb(25, 128, 255);
  }
`)

const adjustXY = (nodes, ratio = 500) => {
  /**
   * 根据光缆等级从高到低依次排序
   * 根据每个站点光缆数量从高低依次排序
   */
  nodes.sort((a, b) => {
    return a.cableLevelIndex > b.cableLevelIndex ? 1 : -1
  })
  const allLevelNodes = [] // 存有等级的站点
  const dictCableLevelList = store.getters.customDictList.filter(i => i.type === 'CABLE_LEVEL')
  dictCableLevelList.forEach(level => {
    const arr = nodes.filter(i => i.cableLevel && i.cableLevel.code === level.code)
    // 同一等级内，再根据站点连接的光缆数量从高到低排序
    arr.sort((a, b) => {
      return a.cableIdList.length < b.cableIdList.length ? 1 : -1
    })
    if (arr.length) {
      // 同一等级内，根据光缆数量，确定每个站点在拓扑中的位置列
      let columnIndex = 1
      let cableNum = arr[0].cableIdList.length
      arr.forEach(i => {
        if (cableNum !== i.cableIdList.length) {
          cableNum = i.cableIdList.length
          columnIndex = 1
        }
        i.columnIndex = columnIndex++
      })
      allLevelNodes.push(...arr)
    }
  })
  const allNoLevelNodes = nodes.filter(i => !i.cableLevel || !i.cableLevel.code) // 存没有等级的站点
  // 先根据站点连接的光缆数量从高到低排序
  allNoLevelNodes.sort((a, b) => {
    return a.cableIdList.length < b.cableIdList.length ? 1 : -1
  })
  if (allNoLevelNodes.length) {
    // 根据光缆数量，确定每个站点在拓扑中的位置列
    let columnIndex = 1
    let cableNum = allNoLevelNodes[0].cableIdList.length
    allNoLevelNodes.forEach(i => {
      // 如果一行的数量超过15个，也需要换行
      if (cableNum !== i.cableIdList.length || columnIndex > 15) {
        cableNum = i.cableIdList.length
        columnIndex = 1
      }
      i.columnIndex = columnIndex++
    })
  }
  const allNodes = [...allLevelNodes, ...allNoLevelNodes]
  if (allNodes.length) {
    let rowIndex = 1
    let cableNum = allNodes[0].cableIdList.length
    let cableLevel = allNodes[0].cableLevel ? allNodes[0].cableLevel.code : ''
    allNodes.forEach(i => {
      if (cableLevel !== i.cableLevel.code || cableNum !== i.cableIdList.length) {
        cableNum = i.cableIdList.length
        cableLevel = i.cableLevel.code
        rowIndex++
      }
      i.rowIndex = rowIndex
      // 如果每一行的数量超过15个，也需要换行展示
      if (i.columnIndex === 15) {
        rowIndex++
      }
      i.x = i.columnIndex * 200
      i.y = i.rowIndex * 200
    })
  }
}

function RenderG6() {
  this.nodes = null
  this.edges = null
  this.combos = null
  this.graph = null
  this.minimap = null
}

RenderG6.prototype = {
  init(options) {
    this.clear()
    const graphCfg = {
      container: options.container,
      width: options.width,
      height: options.height,
      fitView: true,
      // fitViewPadding: [20, 40, 50, 20],
      // layout: {
      //   type: 'force2',
      //   preventOverlap: true,
      //   linkDistance: 200
      // },
      groupByTypes: false,
      modes: {
        default: [
          {
            type: 'drag-canvas',
            enableOptimize: false,
            allowDragOnItem: true
          },
          {
            type: 'zoom-canvas',
            enableOptimize: false
          },
          {
            type: 'click-select',
            selectCombo: false
          }
        ],
        edit: [
          'drag-canvas',
          'zoom-canvas',
          'drag-combo',
          'brush-select',
          {
            type: 'drag-node',
            onlyChangeComboSize: true
          }
        ]
      },
      defaultNode: {
        size: 45,
        style: {
          cursor: 'pointer'
        },
        labelCfg: {
          position: 'bottom',
          style: {
            fontSize: 16
            // stroke: '#fff',
            // lineWidth: 1
          }
        }
      },
      defaultEdge: {
        // type: 'quadratic', // 设置边为贝塞尔曲线
        style: {
          cursor: 'pointer',
          lineWidth: 2,
          lineAppendWidth: 4
        },
        labelCfg: {
          refY: 30,
          autoRotate: true, // 设置标签文字跟随边旋转
          style: {
            opacity: 0
          }
        }
      },
      defaultCombo: {
        type: 'rect',
        padding: [30, 30, 30, 30],
        labelCfg: {
          style: {
            fill: getThemeColor('unifiedFontColor'),
            fontSize: 18
          }
        }
      },
      nodeStateStyles: {
        hover: {
          size: 80
        }
      },
      edgeStateStyles: {
        click: {
          stroke: 'steelblue'
        }
      }
    }
    if (options.showMiniMap) {
      this.addMiniMap(options)
      graphCfg.plugins = [this.minimap]
    }
    this.graph = new G6.Graph(graphCfg)
  },
  setData({ nodes = [], edges = [] }) {
    // 处理节点
    let levels = []
    this.nodes = []
    nodes.forEach(i => {
      i.id = i.id.toString()
      i.labelCfg = {
        style: {
          fill: i.font.color
        }
      }
      i.type = 'image'
      i.img = i.image
      i.comboId = i.cableLevel && i.cableLevel.code
      i.initComboId = i.comboId
      if (i.cableLevel) {
        levels.push(i.cableLevel.code)
      }
      // return i
      this.nodes.push(i)
    })
    // 处理边
    this.edges = []
    edges
      .filter(i => i.from !== i.to)
      .forEach(i => {
        i.source = i.from.toString()
        i.target = i.to.toString()
        i.style = {
          stroke: i.color.color,
          strokeOpacity: i.color.opacity || 0.5,
          lineWidth: i.width || 2
        }
        i.labelCfg = {
          style: {
            fill: i.font.color,
            fontSize: 18
          }
        }
        // return i
        this.edges.push(i)
      })
    // 处理分组
    this.combos = []
    levels = Array.from(new Set(levels))
    const dictCableLevelList = store.getters.customDictList.filter(i => i.type === 'CABLE_LEVEL')
    const cableLevelList = dictCableLevelList.filter(i => levels.includes(i.code))
    cableLevelList.forEach(i => {
      const obj = {}
      obj.id = i.code
      obj.label = i.name
      obj.padding = 20
      obj.style = {
        fill: getThemeColor('topoColor'),
        stroke: getThemeColor('bgColor'),
        opacity: 0.2
      }
      this.combos.push(obj)
    })
    G6.Util.processParallelEdges(this.edges, 15, 'quadratic', 'line') // 2个节点间存在多条边时，设置边不重叠
  },
  addMiniMap(options) {
    const scale = 0.2 // 拓扑图和鹰眼初始比例
    // 添加鹰眼
    this.minimap = new G6.Minimap({
      size: [options.width * scale, options.height * scale],
      className: 'minimap',
      hideEdge: true,
      type: 'delegate'
    })
  },
  update(data, fitView = false) {
    // 更新数据
    if (!this.graph) return
    this.setData(data)
    this.graph.changeData({
      nodes: this.nodes,
      edges: this.edges,
      combos: this.combos
    })
    fitView && this.graph.fitView() // 重新调整下画布
    console.log(`更新画布${fitView ? '并调整画布' : '不调整画布'}`)
  },
  adjustXY() {
    adjustXY(this.nodes)
    this.graph.changeData({
      nodes: this.nodes,
      edges: this.edges,
      combos: this.combos
    })
    this.graph.fitView() // 重新调整下画布
  },
  motoTo(nodeIds) {
    // 根据nodeId获取元素
    const nodes = this.graph.findAll('node', node => {
      return nodeIds.includes(node.get('model').nodeId)
    })
    // const BBox = G6.Util.calculationItemsBBox(nodes) // 获取多个元素组成的包围盒
    // console.log(BBox)
    if (!nodes.length) return
    this.graph.focusItem(nodes[0])
  },
  clear() {
    if (this.graph) {
      console.log('画布清空')
      this.graph.clear() // 清空画布内容
      this.graph.destroy() // 销毁画布
      this.graph.off() // 解除所有元素的监听事件
      this.graph = null
    }
  }
}

export default RenderG6
